package movierecomending;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;

import org.apache.xmlbeans.XmlException;
import org.example.comunicationInputSchema.QueryDocument;
import org.example.comunicationInputSchema.QueryDocument.Query;
import org.example.comunicationInputSchema.QueryDocument.Query.Candidates;
import org.example.comunicationInputSchema.QueryDocument.Query.Candidates.Candidate;
import org.example.comunicationInputSchema.QueryDocument.Query.Candidates.Candidate.Cinema;
import org.example.comunicationInputSchema.QueryDocument.Query.QueryParam;
import org.example.comunicationInputSchema.ReccomendedCinemaDocument;
import org.example.comunicationInputSchema.ReccomendedCinemaDocument.ReccomendedCinema;
import org.example.comunicationInputSchema.ReccomendedCinemaDocument.ReccomendedCinema.Cinema.Film;

import utils.DataBase;

import data.CandidateScore;
import data.CinemaScore;

public class Service {
	DataBase db;
	MatrixInterface matrix;
	MovieFinder mf;
	
	static HashMap<String,CandidateScore> candidates;
	String title;
	String[] keywords;
	String[] genre;
	
	float alpha=(float) 0.7;
	float beta= (float) 0.2;
	float lambda=(float) 0.1;
	
	static String matrixPath="/Users/crisgiannone/Ricerca/tesisti/Valentina_APP/matrix/currentMatrix";

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub

		Service s=new Service(matrixPath);	
		s.getInput("");
		
		HashMap<Integer,CinemaScore> reccomendedCinema=s.computeReccomendingScore();			
		s.sendResponse(reccomendedCinema);
	}
	
	
	public Service(String arg) throws Exception{
		db = DataBase.getInstance();
	    db.ConnectDB();	  
	    matrix=new MatrixInterface(arg);	    
	}
	
	
	public HashMap<Integer,CinemaScore> computeReccomendingScore() throws XmlException, IOException{
		
		HashMap<Integer,CinemaScore> cinemaScore=new HashMap<Integer,CinemaScore>();
		
		CandidateScore c;
		CinemaScore cnm;
		
		double score;
		
		getSimilarityByGenre();				
		getSimilarityByTitle();
		getSimilarityByKeyword();
		
		for (String candidate:candidates.keySet()){
			System.out.println(candidates.get(candidate).getTitle()+			
					" TitleScore: "+candidates.get(candidate).getTitlescore()+
					" KeywordScore: "+candidates.get(candidate).getKeywordscore()+
					" GenreScore: "+candidates.get(candidate).getGenrescore());
		}
		
		for (String candidate:candidates.keySet()){

			c=candidates.get(candidate);
			c.setScore(((c.getTitlescore()*alpha)+(c.getKeywordscore()*beta)+(c.getGenrescore()*lambda))/2.3);
			candidates.put(candidate, c);
		
			for (Cinema cinema:c.getCinema()){	
				if (cinemaScore.containsKey(cinema.getIdcinema())){
					cnm=cinemaScore.get(cinema.getIdcinema());
					score=cnm.getScore()+c.getScore();					
				}else{
					cnm= new CinemaScore(cinema.getIdcinema());
					score=c.getScore();
				}
				cnm.addFilm(c);
				cinemaScore.put(cinema.getIdcinema(), cnm);	
			}
		}
			
		return cinemaScore;
	}
	
	public ReccomendedCinemaDocument sendResponse(HashMap<Integer,CinemaScore> cinemaScore) {

		Film f;
		ReccomendedCinemaDocument document= ReccomendedCinemaDocument.Factory.newInstance();

		for (Integer c:cinemaScore.keySet()){
			ReccomendedCinema cinema=document.addNewReccomendedCinema();
			ReccomendedCinema.Cinema cnm=cinema.addNewCinema();
			cnm.setIdcinema(c.intValue());
			cnm.setScore(cinemaScore.get(c).getScore());
			for (CandidateScore cf:cinemaScore.get(c).getFilms()){
				f= cnm.addNewFilm();
				f.setIdfilm(cf.getIdFilm());
				f.setScore((float) cf.getScore());
			}
			
		}
		System.out.println(document.getReccomendedCinema().getCinemaArray(0).getIdcinema()); 
		
		return document;	
	}

	public void getInput(String xmlInput) throws XmlException, IOException{
		
	  QueryDocument doc = QueryDocument.Factory.parse(xmlInput);		 	  
	  Query root=doc.getQuery();
	  QueryParam q= root.getQueryParam();
	  Candidates s= root.getCandidates();
	  Candidate[] s1= s.getCandidateArray();
	 
	  candidates = new HashMap<String,CandidateScore>();
	  
	  title=q.getTitle();
	  keywords=q.getKeywords().split(";");
	  
	  genre=q.getGenre().split(";");
	  
	  for(Candidate a:s1){
		  candidates.put(a.getTitle(),new CandidateScore(a.getTitle(),a.getCinemaArray(),a.getStory(),a.getIdfilm()));
		  System.out.println(a.getTitle()+" "+a.getStory()+" "+a.getIdfilm());
	  }	 	  
	}
	
	public void  getSimilarityByTitle(){
		candidates=matrix.getSimilarMovie(title, candidates);
	}
	
	public void  getSimilarityByKeyword(){
		candidates=matrix.getSimilarKeyword(keywords, candidates);
	}
	
	public void getSimilarityByGenre(){
		
		CandidateScore c=null;
	
		HashSet<String> d= db.getFilmByGenre(genre);
		
		for(String s:d){ 
			if (candidates.containsKey(d)){
				c= candidates.get(s);
				c.setGenrescore(1);
				candidates.put(s,c);
			}
				
		}
	}
}